#requires -version 2.0 
function Get-NaQtree {
	<#
	.Synopsis
   		Return list of qtrees
	.Description
   		Return list of qtrees
	.Parameter volume
   		Name of the volume to be queried. Do not include a '/vol/' prefix. 
	.Parameter Server
   		NaServer to query
	.Example
   		PS > Get-NaQtree
	.Outputs
    	NetApp.SDK.NaQtree[]
    .Link
    	Remove-NaQtree
    	Rename-NaQtree
    	New-NaQtree
	#>
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param ( 
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,Mandatory=$false,Position=0,HelpMessage="Name of the volume to be queried.")]
		[STRING]
		$Volume,
        
        [Parameter(ValueFromPipelineByPropertyName=$TRUE,Mandatory=$false,Position=1,HelpMessage="Name of the Qtree.")]
		[STRING]
		$QTree,
			
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("qtree-list")
		if ($Volume){
			$request.AddNewChild("volume",$Volume)
		}
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result.qtrees."qtree-info" | % {
				return New-Object NetApp.SDK.NaQtree -ArgumentList @(
					$_."volume",
					$_."qtree",
					$_."security-style",
					$_."status",
					$_."id",
					$_."owning-vfiler",
					$(if ($_."oplocks" -eq "enabled") {$True} else {$False})
				)
			} | ?{$_.Qtree -match $Qtree}
		}
	}
}
function New-NaQtree {
	<#
	.Synopsis
   		Create a new qtree.
	.Description
   		Create a new qtree.
	.Parameter Volume
   		Name of the volume on which to create the qtree 
	.Parameter Qtree
        The path of the qtree, relative to the volume. 
	.Parameter Mode
        The file permission bits of the qtree. Similar to UNIX permission 
        bits: 0755 gives read/write/execute permissions to owner and read/
        execute to group and other users. It consists of 4 octal digits 
        derived by adding up bits 4, 2, and 1. Omitted digits are assumed 
        to be zeros. First digit selects the set user ID (4), set group 
        ID (2), and sticky (1) attributes. The second digit selects 
        permissions for the owner of the file: read (4), write (2), and 
        execute (1); the third selects permissions for other users in the 
        same group; the fourth for other users not in the group. If this 
        argument is missing, use the default value specified in the option 
        "wafl.default_qtree_mode". 
	.Parameter Server
   		NaServer to query
	.Example
   		New-NaQtree -Volume Vol1 -Qtree Foo
	.Outputs
    	NetApp.SDK.NaQtree[]
    .Link
    	Get-NaQtree
    	Remove-NaQtree
    	Rename-NaQtree
	#>
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,Mandatory=$true,Position=0,HelpMessage="Name of the volume on which to create the qtree ")]
		[STRING]
		$Volume,
        
        [Parameter(ValueFromPipelineByPropertyName=$TRUE,Mandatory=$true,Position=1,HelpMessage="The path of the qtree, relative to the volume.")]
		[STRING]
		$Qtree,
        
        [Parameter(ValueFromPipelineByPropertyName=$TRUE,Mandatory=$False,Position=3)]
		[validateScript({$_ -match "[0-7]{4}"})]
		[STRING]
		$Mode,
        
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("qtree-create")
		$request.AddNewChild("qtree",$Qtree)
        $request.AddNewChild("volume",$Volume)
        if ($mode){
			$request.AddNewChild("volume",$mode)
		}
        if ($pscmdlet.ShouldProcess($Server.Server,"Creating Qtree /vol/$($Volume)/$($Qtree)")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				Get-NaQtree -Volume $Volume -Qtree $foo -Server $Server
            }
		}
	}
}
function Rename-NaQtree {
	<#
	.Synopsis
   		Create a new qtree.
	.Description
   		Renames the specified qtree to a new name. If the qtree is referenced
        in the file /etc/exportfs, use NFS API nfs-exportfs-append-rules to 
        modify the file so that the affected file system can be exported by 
        the filer immediately. The "qtree-rename" command does not 
        automatically update the /etc/exports file.
	.Parameter Path
   		Path of an existing qtree. The path should be in this format: /vol/< volume name >/< dst qtree name >. 
	.Parameter NewPath
        Path of new qtree. The path should be in this format: /vol/< volume name >/< dst qtree name >. 
	.Parameter Server
   		NaServer to query
	.Example
   		Rename-NaQtree -path "/vol/Vol1/foo" -NewPath "/vol/vol1/bar"
	.Outputs
    	NetApp.SDK.NaQtree[]
    .Lin
        Get-NaQtree
    	New-NaQtree
    	Rename-NaQtree
	#>
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,Mandatory=$true,Position=0,HelpMessage="Path of an existing qtree")]
		[validateScript({$_ -match "(\/\S+){3}"})]
        [STRING]
		$Path,
        
        [Parameter(ValueFromPipelineByPropertyName=$TRUE,Mandatory=$true,Position=1,HelpMessage="Path of new qtree.")]
		[validateScript({$_ -match "(\/\S+){3}"})]
        [STRING]
		$NewPath,
        
        [Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("qtree-rename")
		$request.AddNewChild("qtree",$Path)
        $request.AddNewChild("new-qtree-name",$NewPath)
        if ($pscmdlet.ShouldProcess($Server.Server,"Renaming $($Path) to $($NewPath)")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
                $null,$null,$v,$Q = ($NewPath -split "/")
				Get-NaQtree -Volume $V -Qtree $Q -Server $Server
            }
		}
	}
}
function Remove-NaQtree {
	<#
	.Synopsis
   		delete the specified qtree
	.Description
   		delete the specified qtree
	.Parameter Path
   		Path of an existing qtree. The path should be in this format: /vol/< volume name >/< dst qtree name >. 
	.Parameter Force
        Force the deletion of the qtree even if it not empty. On using "force" option,
        ZAPI may take a long time to complete because the contents of the entire 
        qtree will have to be deleted before it returns. 
	.Parameter Server
   		NaServer to query
	.Example
   		Remove-NaQtree -path "/vol/Vol1/foo"
	.Outputs
    	NetApp.SDK.NaQtree[]
    .Lin
        Get-NaQtree
    	New-NaQtree
    	Rename-NaQtree
	#>
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="high",DefaultParameterSetName="")]
	param ( 
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,Mandatory=$true,Position=0,HelpMessage="Path of an existing qtree")]
		[validateScript({$_ -match "(\/\S+){3}"})]
        [STRING]
		$Path,
        
        [Parameter()]
		[switch]
		$Force,
        
        [Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("qtree-delete")
		$request.AddNewChild("qtree",$Path)
        if ($Force) {
            $request.AddNewChild("force",$True)
        }
        if ($pscmdlet.ShouldProcess($Server.Server,"Deleting $($Path)")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}
function Set-NaQtree {
	<#
	.Synopsis
   		Set the specified qtree Security Style
	.Description
   		Set the specified qtree Security Style
	.Parameter Path
   		Path of an existing qtree. The path should be in this format: /vol/< volume name >/< dst qtree name >. 
	.Parameter Style
        Security style to be set valid options are "UNIX","NTFS", and "Mixed".
    .Parameter Oplocks
        enable/disable oplocks
	.Parameter Server
   		NaServer to query
	.Example
   		Set-NaQtree -path "/vol/Vol1/foo" -Style NTFS
	.Outputs
    	NetApp.SDK.NaQtree[]
    .Lin
        Get-NaQtree
    	New-NaQtree
    	Rename-NaQtree
        Remove-NaQtree
	#>
	[CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(ParameterSetName="Style",ValueFromPipelineByPropertyName=$TRUE,Mandatory=$true,Position=0,HelpMessage="Path of an existing qtree")]
        [Parameter(ParameterSetName="Oplocks",ValueFromPipelineByPropertyName=$TRUE,Mandatory=$true,Position=0,HelpMessage="Path of an existing qtree")]
		[validateScript({$_ -match "(\/\S+){3}"})]
        [STRING]
		$Path,
        
        [Parameter(ParameterSetName="Style",ValueFromPipelineByPropertyName=$TRUE,Mandatory=$true)]
		[validateSet("UNIX","NTFS","Mixed")]
        [STRING]
		$Style,
        
        [Parameter(ParameterSetName="Oplocks",ValueFromPipelineByPropertyName=$False,Mandatory=$true)]
		[bool]
		$Oplocks,
        
        [Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
        switch ($PSCMDlet.Parametersetname)
        {
            'Style'
            {
                [string]$Command = 'qtree security {0} {1}' -f $Path, $Style
                $msg = "Setting Qtree style to $($Style) on $($Path)"
            }
            'oplocks'
            {
                if ($Oplocks) {
                    [string]$Command = 'qtree oplocks {0} enable' -f $Path
                    $msg = "Enabling oplocks on $($Path)"
                } 
                else {
                    [string]$Command = 'qtree oplocks {0} disable' -f $Path
                    $msg = "Disabling oplocks on $($Path)"
                }
                
            }
        }
		if ($pscmdlet.ShouldProcess($Server.Server,$msg)){
			try {
				Invoke-NaExpression -command $Command -Server $Server | out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
            if ($?){
                $null,$null,$v,$Q = ($Path -split "/")
				Get-NaQtree -Volume $V -Qtree $Q -Server $Server
            }
		}
	}
}